﻿using System.Windows;
using System.Xml;
using System.Xml.Linq;

namespace SHomeWorkshop.LunarPresentation.Commands
{
    public partial class Command
    {
        /// <summary>
        /// 将准备好的“行”集合转换成一个富文本块。
        /// </summary>
        public static void ConvertRowsToRichText()
        {
            if (Globals.selectedEditor == null) return;
            if (Globals.selectedEditor.SelectedExpression == null) return;
            if (Globals.selectedEditor.SelectedExpression is Expressions.Row == false)
            {
                MessageBox.Show("请先选中一个“行”！", Globals.appName,
                    MessageBoxButton.OK, MessageBoxImage.Warning);
                return;//子面板不支持Copy。
            }

            Expressions.Row outRow = Globals.selectedEditor.SelectedExpression as Expressions.Row;

            //看看行中有无其它行。最多两层。
            //如果只有一层，则行中必须是文本块或上下标。
            //如果行中还有行，则内层的各行中只能是文本块或上下标。
            if (ValidateRows(outRow) == false)
            {
                MessageBox.Show("要转换的“行”中存在非法类型的公式。" +
                "要转换的“行”中最多再嵌套一层“行”，内层的“行”将被转换成单独一个段落。" +
                "除此而外，要转换的“行”中只允许存在“文本块”和“上下标式”。",
                    Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            //转换
            XElement element = new XElement("Expression");
            element.SetAttributeValue("Type", "RichText");

            for (int i = 0; i < outRow.FirstSubPanel.BasePanel.Children.Count; i++)
            {
                Expressions.Expression ex = outRow.FirstSubPanel.BasePanel.Children[i] as Expressions.Expression;
                if (ex is Expressions.BaseText)
                {
                    ConvertBaseText(element, ex);
                }
                else if (ex is Expressions.MarkText)
                {
                    ConvertMarkText(element, ex);
                }
                else if (ex is Expressions.Row)
                {
                    Expressions.Row inRow = ex as Expressions.Row;

                    if (i > 0)
                    {
                        element.Add(new XElement("Text", string.Empty));
                    }

                    foreach (UIElement inEx in inRow.FirstSubPanel.BasePanel.Children)
                    {
                        if (inEx is Expressions.BaseText)
                        {
                            ConvertBaseText(element, inEx);
                        }
                        else if (inEx is Expressions.MarkText)
                        {
                            ConvertMarkText(element, inEx);
                        }
                    }

                    if (i < outRow.FirstSubPanel.BasePanel.Children.Count - 1)
                    {
                        element.Add(new XElement("Text", string.Empty));
                    }
                }
            }

            Expressions.Expression newEx =
                Command.InsertExpressionByXmlString(true, element.ToString(), outRow);
            if (newEx != null)
            {
                #region 刷新“AutoWrap”。
                Expressions.RichText newRichText = newEx as Expressions.RichText;
                if (newRichText != null)
                {
                    newRichText.AutoWrap = LunarPresentation.Interfaces.AutoWrapType.FromDoc;
                } 
                #endregion

                ModifingItem mi = new ModifingItem() { OldSelectedExID = outRow.ExID };
                Action actInsert = new Action(newEx.ExID, outRow.ParentPanel.BasePanel.Children.IndexOf(outRow) - 1,
                    newEx.GetType().Name, "InsertExpression", null, element.ToString(),
                    ActionType.Insert, outRow.ParentPanel.ExID);

                mi.Add(actInsert);

                outRow.XmlData.ParentNode.RemoveChild(outRow.XmlData);
                Action actDelete = new Action(outRow.ExID, outRow.ParentPanel.BasePanel.Children.IndexOf(outRow),
                    outRow.GetType().Name, "DeleteExpression", outRow.XmlData.OuterXml, null,
                    ActionType.Delete, outRow.ParentPanel.ExID);
                outRow.ParentPanel.BasePanel.Children.Remove(outRow);

                mi.Add(actDelete);

                newEx.Editor.Do(mi);

                newEx.Editor.SelectedExpression = newEx;
            }
        }

        private static void ConvertBaseText(XElement element, UIElement inEx)
        {
            Expressions.BaseText bt = inEx as Expressions.BaseText;

            if (bt == null)
            {
                MessageBox.Show("传入“ConvertBaseText”方法的参数不是BaseText实例。",
                    Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            XElement newTextElement = new XElement("Text", bt.Text);
            element.Add(newTextElement);

            newTextElement.SetAttributeValue("Foreground",
                ColorPicker.GetBrushName(bt.ExForeground));

            newTextElement.SetAttributeValue("Background",
                ColorPicker.GetBrushName(bt.ExBackground));

            XmlAttribute attrFontWeight = bt.XmlData.GetAttribute("FontWeight");
            if (attrFontWeight != null)
            {
                newTextElement.SetAttributeValue("FontWeight", attrFontWeight.Value);
            }

            XmlAttribute attrFontStyle = bt.XmlData.GetAttribute("FontStyle");
            if (attrFontStyle != null)
            {
                newTextElement.SetAttributeValue("FontStyle", attrFontStyle.Value);
            }

            XmlAttribute attrUnderLine = bt.XmlData.GetAttribute("UnderLine");
            if (attrUnderLine != null)
            {
                newTextElement.SetAttributeValue("UnderLine", attrUnderLine.Value);
            }

            XmlAttribute attrStrikeLine = bt.XmlData.GetAttribute("StrikeLine");
            if (attrStrikeLine != null)
            {
                newTextElement.SetAttributeValue("StrikeLine", attrStrikeLine.Value);
            }

            newTextElement.SetAttributeValue("FontName", bt.FontName);
        }

        private static void ConvertMarkText(XElement newTextElement, UIElement inEx)
        {
            Expressions.MarkText mt = inEx as Expressions.MarkText;

            if (mt == null)
            {
                MessageBox.Show("传入“ConvertMarkText”方法的参数不是MarkText实例。",
                    Globals.appName, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            if (mt.TopMarkText != null && mt.TopMarkText.Length > 0)
            {
                XElement topMarkElement = new XElement("Text", mt.TopMarkText);
                topMarkElement.SetAttributeValue("BaseLineAlignment", "Top");
                newTextElement.Add(topMarkElement);


                topMarkElement.SetAttributeValue("Foreground",
                    ColorPicker.GetBrushName(mt.ExForeground));

                topMarkElement.SetAttributeValue("Background",
                    ColorPicker.GetBrushName(mt.ExBackground));

                XmlAttribute attrFontWeight = mt.XmlData.GetAttribute("FontWeight");
                if (attrFontWeight != null)
                {
                    topMarkElement.SetAttributeValue("FontWeight", attrFontWeight.Value);
                }

                XmlAttribute attrFontStyle = mt.XmlData.GetAttribute("FontStyle");
                if (attrFontStyle != null)
                {
                    topMarkElement.SetAttributeValue("FontStyle", attrFontStyle.Value);
                }

                topMarkElement.SetAttributeValue("FontName", mt.FontName);
            }

            if (mt.BottomMarkText != null && mt.BottomMarkText.Length > 0)
            {
                XElement bottomMarkElement = new XElement("Text", mt.BottomMarkText);
                bottomMarkElement.SetAttributeValue("BaseLineAlignment", "Bottom");
                newTextElement.Add(bottomMarkElement);

                bottomMarkElement.SetAttributeValue("Foreground",
                    ColorPicker.GetBrushName(mt.ExForeground));

                bottomMarkElement.SetAttributeValue("Background",
                    ColorPicker.GetBrushName(mt.ExBackground));

                XmlAttribute attrFontWeight = mt.XmlData.GetAttribute("FontWeight");
                if (attrFontWeight != null)
                {
                    bottomMarkElement.SetAttributeValue("FontWeight", attrFontWeight.Value);
                }

                XmlAttribute attrFontStyle = mt.XmlData.GetAttribute("FontStyle");
                if (attrFontStyle != null)
                {
                    bottomMarkElement.SetAttributeValue("FontStyle", attrFontStyle.Value);
                }

                bottomMarkElement.SetAttributeValue("FontName", mt.FontName);
            }
        }

        /// <summary>
        /// 检查“行”中是否嵌套了不合适的公式。
        /// </summary>
        /// <param name="outRow"></param>
        /// <param name="invalidated"></param>
        /// <returns></returns>
        private static bool ValidateRows(Expressions.Row outRow)
        {
            bool invalidated = false;
            foreach (UIElement ex in outRow.FirstSubPanel.BasePanel.Children)
            {
                if (ex is Expressions.Row)
                {
                    Expressions.Row inRow = ex as Expressions.Row;
                    foreach (UIElement inEx in inRow.FirstSubPanel.BasePanel.Children)
                    {
                        if (inEx is Expressions.BaseText ||
                            inEx is Expressions.MarkText)
                            continue;
                        else
                        {
                            invalidated = true;
                            break;
                        }
                    }
                }
                else if (ex is Expressions.BaseText ||
                   ex is Expressions.MarkText)
                    continue;
                else
                {
                    invalidated = true;
                    break;
                }
            }
            return !invalidated;
        }

        /// <summary>
        /// 将富文本块转换为行。
        /// </summary>
        //public static void ConvertRichTextToRows()
        //{

        //}
    }
}
